package com.hpe.wx.performance.redis.utils;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.log4j.Logger;

public class JMXUtils {
	public static Logger logger = Logger.getLogger(JMXUtils.class.getSimpleName());

	public static Map<String, Number> getOperatingSystemInfo(String jmxUrl, String userName, String password)
			throws IOException, MalformedObjectNameException, AttributeNotFoundException, InstanceNotFoundException,
			MBeanException, ReflectionException {
		Map<String, Number> res = new HashMap<>();
		JMXConnector conn = null;
		MBeanServerConnection mbsc = null;

		conn = getJMXConnector(jmxUrl);
		mbsc = conn.getMBeanServerConnection();

		ObjectName operatingObjName = new ObjectName("java.lang:type=OperatingSystem");

		Long totalPhysicalMemorySize = (Long) mbsc.getAttribute(operatingObjName, "TotalPhysicalMemorySize");
		totalPhysicalMemorySize = totalPhysicalMemorySize < 0 ? 0 : totalPhysicalMemorySize;

		Long freePhysicalMemorySize = (Long) mbsc.getAttribute(operatingObjName, "FreePhysicalMemorySize");
		freePhysicalMemorySize = freePhysicalMemorySize < 0 ? 0 : freePhysicalMemorySize;

		Double systemCpuLoad = Double.parseDouble(mbsc.getAttribute(operatingObjName, "SystemCpuLoad") + "");
		systemCpuLoad = systemCpuLoad < 0 ? 0 : systemCpuLoad;

		Double processCpuLoad = Double.parseDouble(mbsc.getAttribute(operatingObjName, "ProcessCpuLoad") + "");
		processCpuLoad = processCpuLoad < 0 ? 0 : processCpuLoad;

		res.put("TOTALPHYSICALMEMORYSIZE", totalPhysicalMemorySize);
		res.put("FREEPHYSICALMEMORYSIZE", freePhysicalMemorySize);
		res.put("SYSTEMCPULOAD", systemCpuLoad);
		res.put("PROCESSCPULOAD", processCpuLoad);

		closeConnection(conn, mbsc);

		return res;
	}

	public static Map<String, Number> getHeapInfo(String jmxUrl, String userName, String password) {
		Map<String, Number> res = new HashMap<>();
		JMXConnector conn = null;
		MBeanServerConnection mbsc = null;
		try {
			conn = getJMXConnector(jmxUrl);
			mbsc = conn.getMBeanServerConnection();

			ObjectName jvmHeapObjName = new ObjectName("java.lang:type=Memory");

			CompositeDataSupport heapMemoryUsage = (CompositeDataSupport) mbsc.getAttribute(jvmHeapObjName,
					"HeapMemoryUsage");

			Long init = Long.parseLong(heapMemoryUsage.get("init") + ""); // 初始大小
			init = init < 0 ? 0 : init;

			Long max = Long.parseLong(heapMemoryUsage.get("max") + "");
			max = max < 0 ? 0 : max;

			Long committed = Long.parseLong(heapMemoryUsage.get("committed") + "");
			committed = committed < 0 ? 0 : committed;

			Long used = Long.parseLong(heapMemoryUsage.get("used") + "");
			used = used < 0 ? 0 : used;

			res.put("init", init);
			res.put("max", max);
			res.put("committed", committed);
			res.put("used", used);
		} catch (MalformedObjectNameException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (AttributeNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstanceNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MBeanException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ReflectionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			closeConnection(conn, mbsc);
		}

		return res;
	}

	public static Map<String, Object> checkJmxUrlUseable(String jmxUrl) {
		Map<String, Object> res = new HashMap<>();
		try {
			logger.info("The checking jmxUrl is: " + jmxUrl);
			JMXServiceURL serviceURL = new JMXServiceURL(jmxUrl);
			// "service:jmx:rmi:///jndi/rmi://MYDPH0075.hpswlabs.adapps.hp.com:29601/jmxrmi");

			JMXConnectorFactory.connect(serviceURL, null);
			res.put("status", "success");
			res.put("message", "right URL");
		} catch (Exception e) {
			res.put("status", "failed");
			res.put("message", "Error with JMXURL");
			e.printStackTrace();
		}

		return res;
	}

	public static JMXConnector getJMXConnector(String jmxUrl) {
		JMXConnector conn = null;
		try {
			logger.info("The jmxUrl is: " + jmxUrl);
			JMXServiceURL serviceURL = new JMXServiceURL(jmxUrl);
			// "service:jmx:rmi:///jndi/rmi://MYDPH0075.hpswlabs.adapps.hp.com:29601/jmxrmi");
			Map<String, String[]> map = new HashMap<>();
			String[] credentials = new String[] { "monitorRole", "tomcat" };
			map.put("jmx.remote.credentials", credentials);
			conn = JMXConnectorFactory.connect(serviceURL, null);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return conn;
	}

	private static void closeConnection(JMXConnector conn, MBeanServerConnection mbsc) {
		if (null != mbsc) {
			mbsc = null;
		}
		try {
			if (null != conn) {
				conn.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
